﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using PServiceBus.Core.Interface;
using PServiceBus.Core.Runtime.Messages;
using System.Collections;
using PServiceBus.Core.Provider;
using PServiceBus.Core.Runtime.Extensions;
using PServiceBus.Core.Runtime.Transports;
using PServiceBus.Core.Runtime;
using Phoenix.DataAccess;
using System.Resources;
using PServiceBus.MessageStores.Properties;
using Microsoft.Win32;
using System.Data.SqlClient;

namespace PServiceBus.MessageStores {
    public class DefaultMessageStore : IMessageStore {

        #region IMessageStore Members

        private static string ResolveConnectionString(string connectionString) {
            var is64bit = Environment.Is64BitOperatingSystem;
            var reg = is64bit ? RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64) :
                Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Microsoft SQL Server");
            var key = reg.OpenSubKey(@"SOFTWARE\Microsoft\Microsoft SQL Server");
            const string local = "(local)";
            var instances = key.GetValue("InstalledInstances") as string[];
            var instance = (instances != null ? instances.FirstOrDefault() : null) ?? local;
            instance = instance != local ? String.Concat(@".\", instance) : instance;
            return connectionString.Replace(local, instance);
        }

        public void Init() {
            MethodHelper.TryLog(SetupDatabase);
        }

        private void SetupDatabase() {
            Address = ResolveConnectionString(Address);
            var connectionBuilder = new SqlConnectionStringBuilder(Address);
            var masterConnectionString = Address.Replace(connectionBuilder.InitialCatalog, "master");
            Model.Execute(model => model.Query(String.Format(@"
                IF(db_id('{0}') IS NULL)
                BEGIN
                    CREATE DATABASE [{0}];
                END", connectionBuilder.InitialCatalog)), masterConnectionString);
            Model.Execute(model => model.Query(Resources.CREATE_TABLE_SCRIPT), Address);
        }

        public void Store(PublishedMessage message) {
            MethodHelper.TryLog(() => SaveMessage(message, Address));
        }

        private void SaveMessage(PublishedMessage message, string address) {
            if (String.IsNullOrWhiteSpace(address)) return;
            Model.Execute(model =>
                model.Insert("PServiceBus_MessageEx",
                    new
                    {
                        CreateDate = message.CreateDate,
                        TopicName = message.Message.TopicName,
                        Type = message.Type.ToString(),
                        Data = message.Message.Parameters.SelectMany(param => param)
                            .Select(kv => new {kv.Key, kv.Value}).ToList().ToJson(),
                        Headers = message.Message.Headers
                        .Select(kv => new {kv.Key, kv.Value}).ToList().ToJson(),
                        Responses = message.Responses.ToList().ToJson(),
                        Id = message.ID.ToString()
                    })
            , address);
        }

        public string Address { get; set; }
        #endregion
    }
}
